import List from "../list/List";
import Random from "./Random";
import IndexOutOfBoundException from "../exceptions/IndexOutOfBoundException";
import UnmodifiableList from "../list/UnmodifiableList";
import ArrayList from "../list/ArrayList";

/**
 * 一些有用的，针对{@link List}的静态方法。
 *
 * @version 1.0
 */
export default class Lists {

  /**
   * 随机打乱给定的列表。
   *
   * @param list 需要被打乱的数组
   * @throws {UnsupportedOperationException} add方法和set方法不被此列表支持
   * @version 1.0
   */
  public static shuffle<E>(list: List<E>): void {
    for (let i = 0; i < list.size(); i++) {
      const random = Random.randomRange(0, list.size());
      Lists.swap(list, i, random);
    }
  }

  /**
   * 将给定列表中的两个索引上的元素进行互换。
   *
   * @param list 需要进行交换的数组
   * @param a 需要交换的第一个索引
   * @param b 需要交换的第二个索引
   * @throws {IndexOutOfBoundException} 索引超出了数组的范围
   * @throws {UnsupportedOperationException} add方法和set方法不被此列表支持
   * @version 1.0
   */
  public static swap<E>(list: List<E>, a: number, b: number): void {

    if (a < 0 || a > list.size()) {
      throw new IndexOutOfBoundException(a, list.size());
    }

    if (b < 0 || b > list.size()) {
      throw new IndexOutOfBoundException(b, list.size());
    }

    list.set(a, list.set(b, list.get(a)));
  }

  /**
   * 构造一个无法改变的列表。
   *
   * @param values 列表中应包含的元素
   */
  public static of<E>(...values: E[]): UnmodifiableList<E> {
    return new UnmodifiableList<E>(new ArrayList(values, -1));
  }
}
